package com.wxzhou.wangzhuan.api;


import com.wxzhou.wangzhuan.dto.*;
import com.wxzhou.wangzhuan.exception.UserAccountException;
import com.wxzhou.wangzhuan.exception.UserRealNameException;
import com.wxzhou.wangzhuan.exception.UserTaxAgrementException;
import com.wxzhou.wangzhuan.exception.WithdrawException;
import com.wxzhou.wangzhuan.security.UserContext;
import com.wxzhou.wangzhuan.service.WithdrawService;
import com.wxzhou.wangzhuan.util.AdvancedGsonPrettyPrint;
import io.smallrye.mutiny.Uni;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.jboss.logging.Logger;

import java.util.Map;

/**
 * 提现接口
 */
@Path("/api")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class WithdrawApi {

    private static final Logger LOG = Logger.getLogger(WithdrawApi.class);

    @Inject
    WithdrawService withdrawService;

    @Inject
    UserContext userContext;

    /**
     * 检查用户是否已实名
     *
     * @param commonRequestDto
     * @return
     */
    @POST
    @Path("/withdraw-bind-check")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Uni<Response> validBindWithdraw(@Valid UserBindWithdrawRequestDto commonRequestDto) {
        boolean authenticated = userContext.isAuthenticated();
        if (!authenticated) {
            ResponseDto<Object> unauthorized = ResponseDto.unauthorized("");
            return Uni.createFrom().item(Response.status(unauthorized.getCode()).entity(unauthorized).build());
        }
        return withdrawService.checkBindWithdraw(commonRequestDto, userContext.getCurrentUserInfo().get())
                .onItem().transform(response -> {
                    if (response != null) {
                        ResponseDto<UserBindWithdrawCheckResponseDto> resp = ResponseDto.success(response);
                        return Response.ok(resp).build();
                    } else {
                        ResponseDto<Map<String, Object>> resp = ResponseDto.fail("实名校验失败");
                        return Response.status(500).entity(resp).build();
                    }
                })
                .onFailure().recoverWithUni(throwable -> {
                    throwable.printStackTrace();
                    LOG.error("校验实名失败: " + throwable.getMessage(), throwable);
                    ResponseDto<Map<String, Object>> resp = ResponseDto.error("实名校验失败:" + throwable.getMessage());
                    return Uni.createFrom().item(Response.status(500).entity(resp).build());
                });
    }

    /**
     * 实名提交
     *
     * @param commonRequestDto
     * @return
     */
    @POST
    @Path("/realname")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Uni<Response> realnameSubmit(@Valid RealNameBindRequestDto commonRequestDto) {
        boolean authenticated = userContext.isAuthenticated();
        if (!authenticated) {
            ResponseDto<Object> unauthorized = ResponseDto.unauthorized("");
            return Uni.createFrom().item(Response.status(unauthorized.getCode()).entity(unauthorized).build());
        }
        return withdrawService.realnameSubmit(commonRequestDto, userContext.getCurrentUserInfo().get())
                .onItem().transform(response -> {
                    if (response != null) {
                        ResponseDto<Boolean> resp = ResponseDto.success(response);
                        return Response.ok(resp).build();
                    } else {
                        ResponseDto<Map<String, Object>> resp = ResponseDto.fail("实名异常: ");
                        return Response.status(500).entity(resp).build();
                    }
                })
                .onFailure().recoverWithUni(throwable -> {
                    throwable.printStackTrace();
                    LOG.error("实名错误: " + throwable.getMessage(), throwable);
                    ResponseDto<Map<String, Object>> resp = ResponseDto.error("实名异常:" + throwable.getCause().getMessage());
                    if (throwable instanceof UserRealNameException) {
                        return Uni.createFrom().item(Response.status(500).entity(resp).build());
                    } else {
                        resp = ResponseDto.error("实名异常");
                        return Uni.createFrom().item(Response.status(500).entity(resp).build());
                    }
                });
    }


    /**
     * 提现面板数据，包括可提金额、绑定数据、提现金额列表等。
     *
     * @param commonRequestDto
     * @return
     */
    @POST
    @Path("/withdraw-dashboard")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Uni<Response> getWithdrawDashboard(@Valid CommonRequestDto commonRequestDto) {
        boolean authenticated = userContext.isAuthenticated();
        if (!authenticated) {
            ResponseDto<Object> unauthorized = ResponseDto.unauthorized("");
            return Uni.createFrom().item(Response.status(unauthorized.getCode()).entity(unauthorized).build());
        }
        return withdrawService.getWithdrawDashboard(userContext.getCurrentUserInfo().get())
                .onItem().transform(response -> {
                    if (response != null) {
                        ResponseDto<WithdrawDashboardResponseDto> resp = ResponseDto.success(response);
                        return Response.ok(resp).build();
                    } else {
                        ResponseDto<Map<String, Object>> resp = ResponseDto.fail("提现失败: ");
                        return Response.status(500).entity(resp).build();
                    }
                })
                .onFailure().recoverWithUni(throwable -> {
                    throwable.printStackTrace();
                    LOG.errorf(throwable, "提现面板数据获取失败: " + throwable.getMessage());
                    String msg = "";
                    if (throwable instanceof UserAccountException) {
                        msg = throwable.getMessage();
                    }
                    ResponseDto<Map<String, Object>> resp = ResponseDto.error("提现面板数据获取失败:" + msg);
                    return Uni.createFrom().item(Response.status(500).entity(resp).build());

                });
    }


    /**
     * 申请提现
     *
     * @param withdrawRequestDto
     * @return
     */
    @POST
    @Path("/withdraw")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Uni<Response> withdraw(@Valid WithdrawRequestDto withdrawRequestDto) {
        LOG.debug(AdvancedGsonPrettyPrint.prettyPrint(withdrawRequestDto));
        boolean authenticated = userContext.isAuthenticated();
        if (!authenticated) {
            ResponseDto<Object> unauthorized = ResponseDto.unauthorized("");
            return Uni.createFrom().item(Response.status(unauthorized.getCode()).entity(unauthorized).build());
        }
        LOG.debug(AdvancedGsonPrettyPrint.prettyPrint(authenticated));
        return withdrawService.request(withdrawRequestDto, userContext.getCurrentUserInfo().get())
                .onItem().transform(response -> {
                    if (response != null) {
                        ResponseDto<WithdrawResponseDto> resp = ResponseDto.success(response);
                        return Response.ok(resp).build();
                    } else {
                        ResponseDto<Map<String, Object>> resp = ResponseDto.fail("提现失败: " + response.getErrorMessage(), response.getErrorCode());
                        return Response.status(500).entity(resp).build();
                    }
                })
                .onFailure().recoverWithUni(throwable -> {
                    throwable.printStackTrace();
                    LOG.errorf(throwable, "提现申请异常: " + throwable.getMessage());
                    ResponseDto<Map<String, Object>> resp = ResponseDto.error("提现申请失败: " + throwable.getMessage());
                    if (throwable instanceof UserRealNameException) {
                        resp = ResponseDto.error("提现申请失败: " + throwable.getMessage(), 555);
                        return Uni.createFrom().item(Response.status(555).entity(resp).build());
                    } else if (throwable instanceof UserTaxAgrementException) {
                        resp = ResponseDto.error("提现申请失败: 请确认缴税协议!", 666);
                        return Uni.createFrom().item(Response.status(500).entity(resp).build());
                    } else if (throwable instanceof WithdrawException) {
                        return Uni.createFrom().item(Response.status(500).entity(resp).build());
                    } else {
                        return Uni.createFrom().item(Response.status(500).entity(ResponseDto.error("提现申请失败,错误码777")).build());
                    }
                });
    }

    /**
     * 查询用户的提现记录
     *
     * @param withdrawRecordRequestDto 提现申请分页对象
     * @return
     */
    @POST
    @Path("/withdraw-record")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Uni<Response> findWithdrawRecord(@Valid WithdrawRecordRequestDto withdrawRecordRequestDto) {
        boolean authenticated = userContext.isAuthenticated();
        if (!authenticated) {
            ResponseDto<Object> unauthorized = ResponseDto.unauthorized("");
            return Uni.createFrom().item(Response.status(unauthorized.getCode()).entity(unauthorized).build());
        }
        return withdrawService.getPageList(withdrawRecordRequestDto, userContext.getCurrentUserInfo().get())
                .onItem().transform(response -> {
                    ResponseDto success = ResponseDto.success(response);
                    return Response.ok(success).build();
                })
                .onFailure().recoverWithUni(throwable -> {
                    String msg = "";
                    if (throwable instanceof WithdrawException) {
                        msg = throwable.getMessage();
                    }
                    ResponseDto<Map<String, Object>> resp = ResponseDto.error("提现失败" + msg);
                    return Uni.createFrom().item(Response.status(500).entity(resp).build());
                });
    }

    /**
     * 用户同意交税协议
     *
     * @param taxAgreementRequestDto
     * @return
     */
    @POST
    @Path("/withdraw-tax-agreement")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Uni<Response> taxAgreement(@Valid WithdrawTaxAgreementRequestDto taxAgreementRequestDto) {
        boolean authenticated = userContext.isAuthenticated();
        if (!authenticated) {
            ResponseDto<Object> unauthorized = ResponseDto.unauthorized("");
            return Uni.createFrom().item(Response.status(unauthorized.getCode()).entity(unauthorized).build());
        }
        return withdrawService.taxAgreement(userContext.getCurrentUserInfo().get())
                .onItem().transform(response -> {
                    ResponseDto success = ResponseDto.success(response);
                    return Response.ok(success).build();
                })
                .onFailure().recoverWithUni(throwable -> {
                    ResponseDto<Map<String, Object>> resp = ResponseDto.error("协议同意失败,请重试!");
                    return Uni.createFrom().item(Response.status(500).entity(resp).build());
                });
    }


    /**
     * 用户查询本次提现预估交税情况
     *
     * @param withdrawRequestDto
     * @return
     */
    @POST
    @Path("/withdraw-get-tax")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Uni<Response> getTax(@Valid WithdrawRequestDto withdrawRequestDto) {
        boolean authenticated = userContext.isAuthenticated();
        if (!authenticated) {
            ResponseDto<Object> unauthorized = ResponseDto.unauthorized("");
            return Uni.createFrom().item(Response.status(unauthorized.getCode()).entity(unauthorized).build());
        }
        return withdrawService.getTax(withdrawRequestDto, userContext.getCurrentUserInfo().get())
                .onItem().transform(response -> {
                    ResponseDto success = ResponseDto.success(response);
                    return Response.ok(success).build();
                })
                .onFailure().recoverWithUni(throwable -> {
                    ResponseDto<Map<String, Object>> resp = ResponseDto.error("查询交税预估数据失败!");
                    return Uni.createFrom().item(Response.status(500).entity(resp).build());
                });
    }


}
